home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / HENSA / MATHS / PLPLOT / PLPLOT.ZIP / src / plfill.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-30  |  6.6 KB  |  289 lines

  1. /* $Id: plfill.c,v 1.14 1994/06/30 18:22:07 mjl Exp $
  2.  * $Log: plfill.c,v $
  3.  * Revision 1.14  1994/06/30  18:22:07  mjl
  4.  * All core source files: made another pass to eliminate warnings when using
  5.  * gcc -Wall.  Lots of cleaning up: got rid of includes of math.h or string.h
  6.  * (now included by plplot.h), and other minor changes.  Now each file has
  7.  * global access to the plstream pointer via extern; many accessor functions
  8.  * eliminated as a result.
  9.  *
  10.  * Revision 1.13  1994/04/30  16:15:11  mjl
  11.  * Fixed format field (%ld instead of %d) or introduced casts where
  12.  * appropriate to eliminate warnings given by gcc -Wall.
  13.  *
  14.  * Revision 1.12  1994/03/23  08:12:54  mjl
  15.  * Split into two routines, one as a front-end to the driver interface fill
  16.  * routine, and the other as a target of the driver interface when the driver
  17.  * doesn't support the desired fill capability.
  18. */
  19.  
  20. /*    plfill.c
  21.  
  22.     Polygon pattern fill.
  23. */
  24.  
  25. #include "plplotP.h"
  26.  
  27. #define DTOR            0.0174533
  28. #define BINC            50
  29.  
  30. struct point {
  31.     PLINT x, y;
  32. };
  33. static PLINT bufferleng, buffersize, *buffer;
  34.  
  35. /* Static function prototypes */
  36. /* INDENT OFF */
  37.  
  38. static int   compar    (const void *, const void *);
  39. static void  addcoord    (PLINT, PLINT);
  40. static void  tran    (PLINT *, PLINT *, PLFLT, PLFLT);
  41. static void  buildlist    (PLINT, PLINT, PLINT, PLINT, PLINT, PLINT, PLINT);
  42.  
  43. /* INDENT ON */
  44.  
  45. /*----------------------------------------------------------------------*\
  46.  * void plfill()
  47.  *
  48.  * Pattern fills the polygon bounded by the input points.
  49.  * If hardware fill is used, a maximum of PL_MAXPOLY-1 vertices is allowed.
  50.  * The final point is explicitly added if it doesn't match up to the first,
  51.  * to prevent clipping problems.
  52. \*----------------------------------------------------------------------*/
  53.  
  54. void
  55. c_plfill(PLINT n, PLFLT *x, PLFLT *y)
  56. {
  57.     short xpoly[PL_MAXPOLY], ypoly[PL_MAXPOLY];
  58.     PLINT i;
  59.  
  60.     if (plsc->level < 3) {
  61.     plabort("plfill: Please set up window first");
  62.     return;
  63.     }
  64.     if (n < 3) {
  65.     plabort("plfill: Not enough points in object");
  66.     return;
  67.     }
  68.     if (n > PL_MAXPOLY-1) {
  69.     plwarn("plfill: too many points in polygon");
  70.     n = PL_MAXPOLY;
  71.     }
  72.     for (i = 0; i < n; i++) {
  73.     xpoly[i] = plP_wcpcx(x[i]);
  74.     ypoly[i] = plP_wcpcy(y[i]);
  75.     }
  76.  
  77.     if (x[0] != x[n-1] || y[0] != y[n-1]) {
  78.     n++;
  79.     xpoly[n-1] = plP_wcpcx(x[0]);
  80.     ypoly[n-1] = plP_wcpcy(y[0]);
  81.     }
  82.  
  83.     plP_fill(xpoly, ypoly, n);
  84. }
  85.  
  86. /*----------------------------------------------------------------------*\
  87.  * void plfill_soft()
  88.  *
  89.  * Pattern fills in software the polygon bounded by the input points.
  90. \*----------------------------------------------------------------------*/
  91.  
  92. void
  93. plfill_soft(short *x, short *y, PLINT n)
  94. {
  95.     PLINT i, j;
  96.     PLINT xp1, yp1, xp2, yp2, xp3, yp3;
  97.     PLINT k, dinc;
  98.     PLFLT ci, si;
  99.     double temp;
  100.  
  101.     buffersize = 2 * BINC;
  102.     buffer = (PLINT *) malloc((size_t) buffersize * sizeof(PLINT));
  103.     if ( ! buffer) {
  104.     plabort("plfill: Out of memory");
  105.     return;
  106.     }
  107.  
  108. /* Loop over sets of lines in pattern */
  109.  
  110.     for (k = 0; k < plsc->nps; k++) {
  111.     bufferleng = 0;
  112.  
  113.         temp = DTOR * plsc->inclin[k] * 0.1;
  114.         si = sin(temp) * plsc->ypmm;
  115.         ci = cos(temp) * plsc->xpmm;
  116.  
  117.     /* normalize: 1 = si*si + ci*ci */
  118.  
  119.         temp = sqrt((double) (si*si + ci*ci));
  120.     si /= temp;
  121.     ci /= temp;
  122.  
  123.     dinc = plsc->delta[k] * SSQR(plsc->ypmm * ABS(ci),
  124.                      plsc->xpmm * ABS(si)) / 1000.;
  125.  
  126.     if (dinc < 0) dinc = -dinc;
  127.     if (dinc == 0) dinc = 1;
  128.  
  129.     xp1 = x[n-2];
  130.     yp1 = y[n-2];
  131.     tran(&xp1, &yp1, (PLFLT) ci, (PLFLT) si);
  132.  
  133.     xp2 = x[n-1];
  134.     yp2 = y[n-1];
  135.     tran(&xp2, &yp2, (PLFLT) ci, (PLFLT) si);
  136.  
  137. /* Loop over points in polygon */
  138.  
  139.     for (i = 0; i < n; i++) {
  140.         xp3 = x[i];
  141.         yp3 = y[i];
  142.         tran(&xp3, &yp3, (PLFLT) ci, (PLFLT) si);
  143.         buildlist(xp1, yp1, xp2, yp2, xp3, yp3, dinc);
  144.         xp1 = xp2;
  145.         yp1 = yp2;
  146.         xp2 = xp3;
  147.         yp2 = yp3;
  148.     }
  149.  
  150. /* Sort list by y then x */
  151.  
  152.     qsort((void *) buffer, (size_t) bufferleng / 2,
  153.           (size_t) sizeof(struct point), compar);
  154.  
  155. /* OK, now do the hatching */
  156.  
  157.     i = 0;
  158.  
  159.     while (i < bufferleng) {
  160.         xp1 = buffer[i];
  161.         yp1 = buffer[i + 1];
  162.         i += 2;
  163.         xp2 = xp1;
  164.         yp2 = yp1;
  165.         tran(&xp1, &yp1, (PLFLT) ci, (PLFLT) (-si));
  166.         plP_movphy(xp1, yp1);
  167.         xp1 = buffer[i];
  168.         yp1 = buffer[i + 1];
  169.         i += 2;
  170.         if (yp2 != yp1) {
  171.         fprintf(stderr, "plfill: oh oh we are lost\n");
  172.         for (j = 0; j < bufferleng; j+=2) {
  173.             fprintf(stderr, "plfill: %d %d\n",
  174.                 (int) buffer[j], (int) buffer[j+1]);
  175.         }
  176.         continue;    /* Uh oh we're lost */
  177.         }
  178.         tran(&xp1, &yp1, (PLFLT) ci, (PLFLT) (-si));
  179.         plP_draphy(xp1, yp1);
  180.     }
  181.     }
  182.     free((void *) buffer);
  183. }
  184.  
  185. /*----------------------------------------------------------------------*\
  186.  * Utility functions
  187. \*----------------------------------------------------------------------*/
  188.  
  189. static void
  190. tran(PLINT *a, PLINT *b, PLFLT c, PLFLT d)
  191. {
  192.     PLINT ta, tb;
  193.  
  194.     ta = *a;
  195.     tb = *b;
  196.  
  197.     *a = floor((double) (ta * c + tb * d + 0.5));
  198.     *b = floor((double) (tb * c - ta * d + 0.5));
  199. }
  200.  
  201. static void
  202. buildlist(PLINT xp1, PLINT yp1, PLINT xp2, PLINT yp2, PLINT xp3, PLINT yp3,
  203.       PLINT dinc)
  204. {
  205.     PLINT min_y, max_y;
  206.     PLINT dx, dy, cstep, nstep, ploty, plotx;
  207.  
  208.     dx = xp2 - xp1;
  209.     dy = yp2 - yp1;
  210.  
  211.     if (dy == 0) {
  212.     if (yp2 > yp3 && ((yp2 % dinc) == 0)) 
  213.         addcoord(xp2, yp2);
  214.     return;
  215.     }
  216.  
  217.     if (dy > 0) {
  218.     cstep = 1;
  219.     min_y = yp1;
  220.     max_y = yp2;
  221.     }
  222.     else {
  223.     cstep = -1;
  224.     min_y = yp2;
  225.     max_y = yp1;
  226.     }
  227.  
  228.     nstep = (yp3 > yp2 ? 1 : -1);
  229.     if (yp3 == yp2) nstep = 0;
  230.  
  231.     /* Build coordinate list */
  232.  
  233.     ploty = (min_y / dinc) * dinc;
  234.     if (ploty < min_y) ploty += dinc;
  235.  
  236.     for (; ploty <= max_y; ploty += dinc) {
  237.     if (ploty == yp1) continue;
  238.     if (ploty == yp2) {
  239.         if (cstep == -nstep) continue;
  240.         if (yp2 == yp3 && yp1 > yp2) continue;
  241.     }
  242.     plotx = xp1 + floor(((double) (ploty - yp1) * dx) / dy + 0.5);
  243.     addcoord(plotx, ploty);
  244.     }
  245. }
  246.  
  247. static void
  248. addcoord(PLINT xp1, PLINT yp1)
  249. {
  250.     PLINT *temp;
  251.  
  252.     if (bufferleng + 2 > buffersize) {
  253.     buffersize += 2 * BINC;
  254.     temp = (PLINT *) realloc((void *) buffer,
  255.                  (size_t) buffersize * sizeof(PLINT));
  256.     if (!temp) {
  257.         free((void *) buffer);
  258.         plexit("plfill: Out of memory!");
  259.     }
  260.     buffer = temp;
  261.     }
  262.  
  263.     buffer[bufferleng++] = xp1;
  264.     buffer[bufferleng++] = yp1;
  265. }
  266.  
  267. static int
  268. compar(const void *pnum1, const void *pnum2)
  269. {
  270.     const struct point *pnt1, *pnt2;
  271.  
  272.     pnt1 = (const struct point *) pnum1;
  273.     pnt2 = (const struct point *) pnum2;
  274.  
  275.     if (pnt1->y < pnt2->y)
  276.     return -1;
  277.     else if (pnt1->y > pnt2->y)
  278.     return 1;
  279.  
  280.     /* Only reach here if y coords are equal, so sort by x */
  281.  
  282.     if (pnt1->x < pnt2->x)
  283.     return -1;
  284.     else if (pnt1->x > pnt2->x)
  285.     return 1;
  286.  
  287.     return 0;
  288. }
  289.